package com.tom.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.tom.constants.RedisConstants;
import com.tom.domain.CourseType;
import com.tom.mapper.CourseTypeMapper;
import com.tom.service.ICourseTypeService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.tom.util.AjaxResult;
import com.tom.vo.CrumbsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author pengh.liu
 * @since 2021-11-26
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {


    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private CourseTypeMapper courseTypeMapper;

    // 在操作数据库中先删除数据在清除redis中的数据
    @Override
    @CacheEvict(cacheNames = RedisConstants.PREFIX_NAME, key = RedisConstants.KEY_ALL_COURSE_TYPE_TREE)
    public boolean deleteById(Serializable id) {
        boolean bool = super.deleteById(id);
//        if (bool){
//            redisTemplate.delete(RedisConstants.KEY_ALL_COURSE_TYPE_TREE);
//        }
        return bool;
    }

    // 在操作数据库中先删除数据在清除redis中的数据
    @Override
    @CacheEvict(cacheNames = RedisConstants.PREFIX_NAME, key = RedisConstants.KEY_ALL_COURSE_TYPE_TREE)
    public boolean insert(CourseType entity) {
        boolean bool = super.insert(entity);
//        if (bool){
//            redisTemplate.delete(RedisConstants.KEY_ALL_COURSE_TYPE_TREE);
//        }
        return bool;
    }

    // 在操作数据库中先删除数据在清除redis中的数据
    @Override
    @CacheEvict(cacheNames = RedisConstants.PREFIX_NAME, key = RedisConstants.KEY_ALL_COURSE_TYPE_TREE)
    public boolean updateById(CourseType entity) {
        Boolean bool = super.updateById(entity);
//        if (bool){
//            redisTemplate.delete(RedisConstants.KEY_ALL_COURSE_TYPE_TREE);
//        }
        return bool;
    }

    public AjaxResult getTree2() {
        // 方式一需要遍历的次数太多嵌套了for循环
        // 先查找所有数据
//        List<CourseType> allList = courseTypeMapper.selectList(null);
//        ArrayList<CourseType> frist = new ArrayList<>();
//        allList.forEach(courseType->{
//            // 查找为第一级目录的数据
//            if (courseType.getPid() == null || courseType.getPid().longValue() == 0L){
//                frist.add(courseType);
//            }else {
//                allList.forEach(courseType1 -> {
//                    // 不是第一级目录的数据直接找自己的父级然后加入父级的children字段
//                    if (courseType.getPid().longValue() == courseType1.getId().longValue()){
//                        List<CourseType> children = courseType1.getChildren();
//                        children.add(courseType); break;

//                    }
//                });
//            }
//        });
        // 方式二在业务层处理但是遍历的次数减少
        // 先查找所有数据
        List<CourseType> allList = courseTypeMapper.selectList(null);
        ArrayList<CourseType> frist = new ArrayList<>();
        Map<Long, CourseType> map = allList.stream().collect(Collectors.toMap(CourseType::getId, CourseType -> CourseType));
        allList.forEach(courseType->{
            // 查找为第一级目录的数据
            if (courseType.getPid() == null || courseType.getPid().longValue() == 0L){
                frist.add(courseType);
            }else {
                // 不是第一级目录
                CourseType courseType1 = map.get(courseType.getPid());
                courseType1.getChildren().add(courseType);
            }
        });

        // 方式三在xml中处理
//        List<CourseType> list = courseTypeMapper.getTree(0L);
//        if (list == null){
//            throw new GloblException("没找到树");
//        }
        return AjaxResult.me().setResultObj(frist);
    }

    /**
     * 使用redis存储类型里面的树状结构
     * @return
     */
    @Override
    @Cacheable(cacheNames = RedisConstants.PREFIX_NAME, key = RedisConstants.KEY_ALL_COURSE_TYPE_TREE)
    public AjaxResult getTree() {
//        List<CourseType> list = (List<CourseType>) redisTemplate.opsForValue().get(RedisConstants.KEY_ALL_COURSE_TYPE_TREE);
//        if (list == null){
            AjaxResult tree2 = getTree2();
//            redisTemplate.opsForValue().set(RedisConstants.KEY_ALL_COURSE_TYPE_TREE, tree2.getResultObj(), 30, TimeUnit.MINUTES);
            return tree2;
//        }
//        return AjaxResult.me().setResultObj(list);
    }

    @Override
    public void addTotalCountByIds(int i, String[] pids) {
        courseTypeMapper.addTotalCountByIds(i,pids);
    }

    /**
     * 查询面包屑
     * @param courseTypeId
     * @return
     */
    @Override
    public AjaxResult getCrumbs(Long courseTypeId) {
        // 更具分类id查询课程分类
        CourseType courseType = super.selectById(courseTypeId);
        // 拿到path进行切割
        String[] split = courseType.getPath().split("\\.");

        // 批量查询课程分类
        List<CourseType> list = super.selectBatchIds(Arrays.asList(split));
        ArrayList<CrumbsVo> crumbsVoList = new ArrayList<>();
        // 循环课程分类，一个分类分装成CrumbsVo
        list.forEach(courseType2 -> {
            // 新建一个返回到前端的对象
            CrumbsVo crumbsVo = new CrumbsVo();
            // 查出父级的类型对象
            EntityWrapper wrapper = new EntityWrapper();
            wrapper.eq("pid", courseType2.getPid());
            List list1 = super.selectList(wrapper);
            // 排除自己展示
            list1.remove(courseType2);
            // 将当前的兄弟姐妹放到crumbsVo的其他对象中
            crumbsVo.setOtherCourseTypes(list1);

            // 设置好crumbsVo中的OwnerCourseType
            crumbsVo.setOwnerCourseType(courseType2);
            crumbsVoList.add(crumbsVo);
        });
        // 要为每个分类，查询统计列表添加到CrumbsVo
        // 所有的CrumbsVo装到一个list返回

        return AjaxResult.me().setSuccess(true).setResultObj(crumbsVoList);
    }

}
